package com.im.test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {

	
	public static void main(String[] args) throws IOException {
		
		Selector serverSelector = Selector.open();
		Selector clientSelector = Selector.open();
		
		
		new Thread(()->{
			
			try {
				
				ServerSocketChannel listenerChannel = ServerSocketChannel.open();
				listenerChannel.socket().bind(new InetSocketAddress(8000));
				listenerChannel.configureBlocking(false);
				listenerChannel.register(serverSelector, SelectionKey.OP_ACCEPT);
				
				while(true){
					
					if(serverSelector.select(1) > 0){
						Set<SelectionKey> set = serverSelector.selectedKeys();
						
						Iterator<SelectionKey> iterator = set.iterator();
						
						while(iterator.hasNext()){
							
							SelectionKey o = iterator.next();
							
							if(o.isAcceptable()){
								
								try {
									SocketChannel clientChannel = ((ServerSocketChannel)o.channel()).accept();
									clientChannel.configureBlocking(false);
									clientChannel.register(clientSelector, SelectionKey.OP_READ);
								} finally {
									iterator.remove();
								} 
							}
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}).start();
		
		
		new Thread(() -> {
			
			while(true){
				
				try {
					if(clientSelector.select(1) > 0){
						Set<SelectionKey> set = clientSelector.selectedKeys();
						Iterator<SelectionKey> iterator = set.iterator();
						
						while(iterator.hasNext()){
							SelectionKey o = iterator.next();
							
							if(o.isReadable()){
								
								try {
									
									SocketChannel clientChannel = (SocketChannel)o.channel();
									ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
									
									clientChannel.read(byteBuffer);
									byteBuffer.flip();
									System.out.println(Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());
								} finally {
									
									iterator.remove();
									o.interestOps(SelectionKey.OP_READ);
								}
								
								
							}
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
}
